/******************************************************************************

                  版权所有 (C), 2019-2029, SDC OS 开源软件小组所有

 ******************************************************************************
  文 件 名   : user_app.h
  版 本 号   : 初稿
  作      ：s30001871
  生成日期   : 2019年6月8日
  最近修改   :
  功能描述   : 创建用户自定义APP对象
  函数列表   :
  修改历史   :
  1.日    期   : 2020年7月4日
    作      ：s30001871
    修改内容   : 创建文件

******************************************************************************/
#ifndef __USER_APP_H__
#define __USER_APP_H__

#include <memory>
#include "msd/channel.hpp"
#include <opencv2/opencv.hpp>
#include <map>

#include "yolov3_app.h"
#include "nnie_service.h"
#include "BYTETracker.h"
#include "inout_tracker.h"
#include "opencv_api.h"
#include "middleware.h"
#include "image_cache.h"
#include "algv.h"

using namespace gc;
using namespace cv;

extern std::mutex gc_app_config_mutex;
extern GC_APP_CONFIG gc_app_config;
extern std::mutex last_track_data_mutex;
extern GCTrackData last_track_data;
extern float m_mapRatio;
// extern caches::fixed_sized_cache<const char*, cv::Mat, caches::LRUCachePolicy> IMG_CACHE;

extern void generateSn(sdc_preset_pos* preset_pos, std::string& sn);

namespace HWApp
{
enum class AppType
{
    APP_TYPE_LPD,
};

// 创建APP对象
std::shared_ptr<Yolov3App> CreateYolov3App(AppType type);

class AIPlus : public Yolov3App
{
public:
    AIPlus(void);
    virtual ~AIPlus(void);

    virtual int32_t LoadModel(unsigned int loadMode, std::string &modelPath);

protected:
    virtual void PretreatObjectData(SDC_SSD_OBJECT_INFO_S &data);
    virtual void ClassifyTargets(uint32_t uclass, uint8_t target[20]);
    virtual void PrintObjectInfo(const SDC_SSD_OBJECT_INFO_S &info) const;

    virtual int32_t NNieParamInit(void);

    virtual void GetDataThrd(void); // 视频服务线程
    virtual void ForwardThrd(void); // YUV处理线程
    
    virtual void StartEventSubscriberThread(void);

    virtual void StartAllThread(void); // 启动所有线程

    // 构造元数据 发送元数据到web/s100端
    virtual bool ConstructTlvMetaData(GCTrackData &yuv_data); // 构建的TLV数据

private:
    int32_t ConvertForwardResult(std::vector<ObjBox> &objBoxs, SDC_SSD_RESULT_S &stResult);
    int32_t ConvertTrackResult(std::vector<STrack> &output_stracks, SDC_SSD_RESULT_S &stResult);
    void Track(GCTrackData &track_data);

    void EventSubscriberThrd(void);

    void AppEpollThrd(void);

    void UploadStateImageThrd(void);
    void TrackThrd(void);
    void InoutThrd(void);
    void ClearThrd(void);
    void AlgvThrd(void);

    void PreProcessYuvData(sdc_yuv_frame_s &frame, uint8_t *&yuv, cv::Mat &dst);
    void PreProcessYuvData(sdc_yuv_frame_s &frame, uint8_t *&yuv, cv::Mat &dst, std::string &save_path);

    struct sdc_yuv_frame_stru CombineYuvData(struct sdc_yuv_data_stru *data,uint32_t w,uint32_t h, bool keep_ratio = false);
    struct sdc_yuv_frame_stru Combined(int fd,const struct sdc_yuv_frame_stru frames[4], const struct sdc_resolution_stru *combined_resolution,struct sdc_yuv_frame_stru *yuv_img, bool keep_ratio = false);
    void combined_yuv_free(int fd, const struct sdc_yuv_frame_stru *yuv_frame);
    int encode_jpeg(sdc_yuv_frame_s &yuv_frame, sdc_osd_region_s &osd_region, sdc_jpeg_frame_s &jpeg_frame) const;
    int free_encoded_jpeg(sdc_jpeg_frame_s &jpeg_frame) const;       
    int save_jpeg(sdc_jpeg_frame_s &jpeg_frame, string &jpegPath) const;

private:
    NNIE *m_nnie;
    NNIE *m_nnie_plate;

    std::string m_curr_tracking_camera_key; // 当前追踪的相机key
    std::map<std::string, BYTETracker*> m_byte_trackers;
    std::map<std::string, InoutTracker*> m_inout_trackers;

    std::thread m_appEpoll_thread;

    bool b_event_subscriber_thread_run;
    std::thread m_event_subscriber_thread;

    bool b_upload_state_image_thread_run;
    std::thread m_upload_state_image_thread;

    bool b_track_thread_run;
    std::thread m_track_thread;

    bool b_inout_thread_run;
    std::thread m_inout_thread;

    // bool b_clear_thread_run;
    // std::thread m_clear_thread;

    bool b_algv_thread_run;
    std::thread m_algv_thread;

    msd::channel<GCTrackData> m_chan_yuv_data{64}; // yuv帧数据
    msd::channel<GCTrackData> m_chan_track_data{64}; // 检测结果数据，待追踪
    msd::channel<vector<InoutTrack>> m_chan_inout_data{64}; // 行为结果数据，待车牌识别、上报

    GCAlgV m_algv;

    GC_YOLO_VERSION m_yolo_version;
};
}
#endif /* __USER_APP_H__ */